package com.baichen.eventloop;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class EventLoopGroupImpl implements EventLoopGroup {

    private final EventLoop[] eventLoops;

    private final AtomicInteger currentIndex = new AtomicInteger(0);

    public EventLoopGroupImpl(int size) {
        if (size <= 0) {
            throw new IllegalArgumentException("EventLoopGroup size must be greater than 0");
        }
        eventLoops = new EventLoop[size];
        for (int i = 0; i < size; i++) {
            eventLoops[i] = new EventLoopImpl();
        }
    }

    @Override
    public void execute(Runnable task) {
        if (task instanceof TargetRunnable targetRunnable) {
            int index = targetRunnable.getIndex();
            if (index < 0 || index >= eventLoops.length) {
                throw new IllegalArgumentException("Invalid index for TargetRunnable: " + index);
            }
            eventLoops[index].execute(targetRunnable);
        } else {
            next().execute(task);
        }
    }

    @Override
    public void schedule(Runnable task, long delay, TimeUnit unit) {
        if (task instanceof TargetRunnable targetRunnable) {
            int index = targetRunnable.getIndex();
            if (index < 0 || index >= eventLoops.length) {
                throw new IllegalArgumentException("Invalid index for TargetRunnable: " + index);
            }
            eventLoops[index].schedule(targetRunnable, delay, unit);
        } else {
            next().schedule(task, delay, unit);
        }
    }

    @Override
    public void scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) {
        if (task instanceof TargetRunnable targetRunnable) {
            int index = targetRunnable.getIndex();
            if (index < 0 || index >= eventLoops.length) {
                throw new IllegalArgumentException("Invalid index for TargetRunnable: " + index);
            }
            eventLoops[index].scheduleAtFixedRate(targetRunnable, initialDelay, period, unit);
        } else {
            next().scheduleAtFixedRate(task, initialDelay, period, unit);
        }
    }

    @Override
    public EventLoop next() {
        return eventLoops[currentIndex.getAndIncrement()];
    }
}
